/**
 * 对象间耦合
 */
var Observe = (function() {
    // 防止消息队列暴露而将篡改故将消息容器作为静态私有变量保存
    var _messages = {};
    return {
        // 注册信息接口
        regist: function(type, fn) {
            if (typeof _messages[type] === 'undefined') {
                _messages[type] = [fn];
            } else {
                _messages[type].push(fn);
            }
        },
        // 发布信息接口
        fire: function(type, args) {
            if (!_messages[type]) return;
            // 定义消息信息
            var events = {
                type: type,                 //消息类型
                args: args || {}            //消息携带数据
            },
            i = 0,                          //消息动作循环变量
            len = _messages[type].length;   //消息动作长度
            for(; i < len; i++) {
                _messages[type][i].call(this, events);
            }
        },
        // 移除信息接口
        remove: function(type, fn) {
            // 如果消息动作队列存在
            if(_messages[type] instanceof Array) {
                // 从最后一个消息动作遍历
                var i = _messages[type].length - 1;
                for(; i >= 0; i--) {
                    // 如果存在该动作则在消息动作序列中移除相应动作
                    _messages[type][i] === fn && _messages[type].splice(i, 1);
                }
            }
        }
    };
})();

// 学生类
var Student = function(result) {
    var that = this;

    that.result = result;
    that.say = function() {
        console.log(that.result);
    }
}

Student.prototype.answer = function(question) {
    Observe.regist(question, this.say);
}

Student.prototype.sleep = function(question) {
    console.log(this.result + ' ' + question + ' 已被注销');
    // 取消对老师问题的监听
    Observe.remove(question, this.say);
}

var Teacher = function() {};
Teacher.prototype.ask = function(question) {
    console.log('问题是：' + question);
    // 发布提问消息
    Observe.fire(question);
}

var student1 = new Student('学生1回答问题'),
    student2 = new Student('学生2回答问题'),
    student3 = new Student('学生3回答问题');

student1.answer('什么是设计模式');
student1.answer('简述观察者模式');
student2.answer('什么是设计模式');
student3.answer('什么是设计模式');
student3.answer('简述观察者模式');

student3.sleep('简述观察者模式');

var teacher = new Teacher();

teacher.ask('什么是设计模式');
teacher.ask('简述观察者模式');

// 学生3回答问题 简述观察者模式 已被注销
// 问题是：什么是设计模式
// 学生1回答问题
// 学生2回答问题
// 学生3回答问题
// 问题是：简述观察者模式
// 学生1回答问题
